package com.hyt.it.ogt.kq.service.bm.service.impl;

import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson15.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hyt.common.utils.result.Result;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.DateUtils;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoOptionService;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.kq.common.bm.enums.BmCostType;
import com.hyt.it.ogt.kq.common.bm.enums.BmMidOrderPayRefundStatus;
import com.hyt.it.ogt.kq.common.bm.enums.BmMidOrderPayStatus;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayBusinessFlowType;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayDeviceEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayStatusEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectNeedPayEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectVerifyEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmSubjectNeedPayEnum;
import com.hyt.it.ogt.kq.common.bm.enums.pay.PayProviderType;
import com.hyt.it.ogt.kq.common.bm.enums.pay.YbPayResultCodeEnum;
import com.hyt.it.ogt.kq.common.bm.utils.DateUtil;
import com.hyt.it.ogt.kq.common.bm.utils.UniqueIDUtils;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.service.bm.feign.tps.TpsClient;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderBusinessFlowMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentPayMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentSubjectMapper;
import com.hyt.it.ogt.kq.service.bm.model.dto.PayStudentSubjectDTO;
import com.hyt.it.ogt.kq.service.bm.model.dto.pay.OrderQueryPayerInfoResult;
import com.hyt.it.ogt.kq.service.bm.model.dto.pay.OrderQueryYopQueryOrderResDTOResult;
import com.hyt.it.ogt.kq.service.bm.model.dto.pay.OrderQueryYopQueryOrderResDTOResultTemp;
import com.hyt.it.ogt.kq.service.bm.model.entity.Order;
import com.hyt.it.ogt.kq.service.bm.model.entity.OrderBusinessFlow;
import com.hyt.it.ogt.kq.service.bm.model.entity.Project;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentPayInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentProject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubject;
import com.hyt.it.ogt.kq.service.bm.model.vo.OrderInfoVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.PayListVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.PayVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.StudentSubjectList;
import com.hyt.it.ogt.kq.service.bm.pay.NcNonTaxPayCallBackData;
import com.hyt.it.ogt.kq.service.bm.pay.NcNonTaxPayCallBackParams;
import com.hyt.it.ogt.kq.service.bm.service.IProjectExamService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentInfoService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentPayService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentSyncRecodeService;
import com.hyt.it.ogt.kq.service.gov.api.bm.BmApi;
import com.hyt.loginfo.service.IBaseLoginService;
import com.hyt.loginfo.service.IUaUserExtService;
import com.hyt.model.PageParam;
import com.hyt.model.tps.entity.PeePayNotify;
import com.hyt.model.tps.vo.Analysis;
import com.hyt.model.tps.vo.PayRequestGoodItem;
import com.hyt.model.tps.vo.PayRequestVo;
import com.hyt.util.JsonUtil;
import com.upay.sdk.FastJsonUtils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class IStudentPayServiceImpl extends BaseServiceImpl<StudentPayMapper, StudentInfo> implements IStudentPayService {

	@Resource
	private ConfigManager configManager;
	@Resource
	private StudentPayMapper studentPayMapper;
	@Resource
	private BmApi kwGovClient;
	@Resource
	private ProjectMapper projectMapper;
	@Resource
	private OrderMapper orderMapper;
	@Resource
	private IProjectSubjectService iProjectSubjectService;
	@Resource
	private IProjectCollectInfoService iProjectCollectInfoService;
	@Resource
	private IProjectCollectInfoOptionService iProjectCollectInfoOptionService;
	@Resource
	TpsClient tpsClient;
	@Resource
	private IProjectExamService iProjectExamService;
	@Resource
	private StudentSubjectMapper studentSubjectMapper;
	@Resource
	private IProjectService iProjectService;
	@Resource
	private IStudentProjectService iStudentProjectService;
	@Resource
	private IStudentSyncRecodeService studentSyncRecodeService;
	@Resource
	private OrderBusinessFlowMapper orderBusinessFlowMapper;
	@Resource
	private IUaUserExtService uaUserExtService;
	@Resource
	private IStudentInfoService iStudentInfoService;
	@Resource
	private RedisTemplate<String, String> redisTemplate;
    @Resource
    private StudentProjectMapper studentProjectMapper;
    @Resource
    private IBaseLoginService iBaseLoginService;

	@Lookup
	public PayRequestVo getPayBase() {
		return null;
	}

	@Override
	public Map<String, Object> queryPayInfo(String studentId) {
		Map<String, Object> mapResult = new HashMap<>();
		StudentPayInfo studentPayInfo = new StudentPayInfo();
		// 不允许60秒内同一个学生同一个任务发起两次支付
		String orderTime = studentPayMapper.getOrderTimeByStudentId(studentId);
		if (StringUtils.isNotBlank(orderTime)) {
			Date createDate = DateUtil.stringToDate(orderTime);
			long interval = (new Date().getTime() - createDate.getTime()) / 1000; // 计算两个日期时间的秒数
			Long payInterval = Long.parseLong("60");
			if (interval < payInterval) {
				// 这里强制停止缴费
				mapResult.put("code", "15038");
				return mapResult;
			}
		}

		// 考生姓名、任务名称
		Map<String, String> map = studentPayMapper.getStudentName(studentId);
		String studentName = "";
		String projectName = "";
		String projectId = "";
		if (MapUtils.isNotEmpty(map)) {
			studentName = map.get("studentName");
			projectName = map.get("projectName");
			projectId = map.get("projectId");
		}
		studentPayInfo.setProjectId(projectId);
		studentPayInfo.setStudentName(studentName);
		studentPayInfo.setProjectName(projectName);

		Project project = projectMapper.selectById(projectId);
		// 判断项目是否需要审核
		if (null != project && BmProjectNeedPayEnum.UNPAY.getPayStatus().equals(project.getIsPay())) {
			// 项目设置不需要缴费
			mapResult.put("code", "15046");
			return mapResult;
		}
		// 项目需要审核
		String isVerify = null;
		if (null != project && BmProjectVerifyEnum.VERIFY.getVerifyStatus().equals(project.getIsVerify())) {
			isVerify = BmProjectVerifyEnum.VERIFY.getVerifyStatus().toString();
			Integer audit = studentPayMapper.getAuditByStudentId(studentId);
			if (audit != 1) {
				// 不通过--您报名的科目暂未通过审核，请等待通过审核再进行缴费。
				mapResult.put("code", "15048");
				return mapResult;
			}
		}

		// 查询报名科目信息
		List<StudentSubjectList> list = studentPayMapper.getStuSubject(projectId, studentId, isVerify);
		if (CollUtil.isEmpty(list)) {
			// 暂无缴费科目
			mapResult.put("code", "15044");
			return mapResult;
		}
		// 考试科目拼接
		StringBuilder subjectNameStr = new StringBuilder();
		// id集合
		StringBuilder subjectIdStr =  new StringBuilder();
		// 价格集合
		StringBuilder subjectPriceStr = new StringBuilder();
		// 报名费用
		BigDecimal price = new BigDecimal("0.00");
		for (StudentSubjectList studentSubject : list) {
		    if(BmSubjectNeedPayEnum.PAY.getPayStatus().equals(studentSubject.getIsPay()) && !Integer.valueOf(1).equals(studentSubject.getPay())) {
		        subjectNameStr.append(studentSubject.getSubjectName()).append(",");
		        subjectIdStr.append(studentSubject.getId()).append(",");
	            if (null != studentSubject.getPrice()) {
	                subjectPriceStr.append(studentSubject.getPrice()).append(",");
	                price = price.add(studentSubject.getPrice());
	            }
	            studentPayInfo.setRegId(studentSubject.getRegId());
	            studentPayInfo.setStudentId(studentSubject.getStudentId());
		    }
			
		}
		log.info("# queryPayInfo: subjectPriceStr:{},subjectIdStr:{},subjectNameStr:{}", subjectPriceStr, subjectIdStr, subjectNameStr);
		studentPayInfo.setSubjectPriceList(subjectPriceStr.deleteCharAt(subjectPriceStr.length()-1).toString());
		studentPayInfo.setSubjectIds(subjectIdStr.deleteCharAt(subjectIdStr.length()-1).toString());
		studentPayInfo.setPrice(price);
		studentPayInfo.setActrualPrice(price);
		studentPayInfo.setSubjectNames(subjectNameStr.deleteCharAt(subjectNameStr.length()-1).toString());

		// 优惠活动（暂时没加）
		mapResult.put("code", "14001");
		mapResult.put("studentPayInfo", studentPayInfo);
		return mapResult;
	}

	@Override
	public Map<String, Object> queryPayInfo2(String studentId) {
		Map<String, Object> mapResult = new HashMap<>();
		StudentPayInfo studentPayInfo = new StudentPayInfo();
		// 考生姓名、任务名称
		Map<String, String> map = studentPayMapper.getStudentName(studentId);
		String studentName = "";
		String projectName = "";
		String projectId = "";
		if (MapUtils.isNotEmpty(map)) {
			studentName = map.get("studentName");
			projectName = map.get("projectName");
			projectId = map.get("projectId");
		}
		studentPayInfo.setProjectId(projectId);
		studentPayInfo.setStudentName(studentName);
		studentPayInfo.setProjectName(projectName);

		Project project = projectMapper.selectById(projectId);
		// 判断项目是否需要缴费
		if (null != project && BmProjectNeedPayEnum.UNPAY.getPayStatus().equals(project.getIsPay())) {
			// 项目设置不需要缴费
			mapResult.put("code", "15046");
			return mapResult;
		}
		// 项目需要审核
		String isVerify = null;
		if (null != project && BmProjectVerifyEnum.VERIFY.getVerifyStatus().equals(project.getIsVerify())) {
			isVerify = BmProjectVerifyEnum.VERIFY.getVerifyStatus().toString();
			Integer audit = studentPayMapper.getAuditByStudentId(studentId);
			if (audit != 1) {
				// 不通过--您报名的科目暂未通过审核，请等待通过审核再进行缴费。
				mapResult.put("code", "15048");
				return mapResult;
			}
		}

		// 查询报名科目信息
		List<StudentSubjectList> list = studentPayMapper.getStuSubject(projectId, studentId, isVerify);
		if (list == null || list.size() == 0) {
			// 暂无缴费科目
			mapResult.put("code", "15044");
			return mapResult;
		}
		// 考试科目拼接
		String subjectNameString = "";
		// id集合
		String idString = "";
		// 价格集合
		String subjectPriceList = "";
		// 报名费用
		BigDecimal price = new BigDecimal("0.00");
		for (StudentSubjectList sList : list) {
			subjectNameString += sList.getSubjectName() + ",";
			idString += sList.getId() + ",";
			if (null != sList.getPrice()) {
				subjectPriceList += sList.getPrice() + ",";
				price = price.add(sList.getPrice());
			}
			studentPayInfo.setRegId(sList.getRegId());
			studentPayInfo.setStudentId(sList.getStudentId());
		}
		studentPayInfo.setSubjectPriceList(subjectPriceList);
		studentPayInfo.setSubjectIds(idString);
		studentPayInfo.setPrice(price);
		studentPayInfo.setActrualPrice(price);
		studentPayInfo.setSubjectNames(subjectNameString.substring(0, subjectNameString.length() - 1));

		// 优惠活动（暂时没加）
		mapResult.put("code", "14001");
		mapResult.put("studentPayInfo", studentPayInfo);
		return mapResult;
	}

	/**
	 * 去支付
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> pay(PayVo payVo) {
		// 项目信息
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			PayRequestVo payBase = getPayBase();

			// 获取项目信息
			Project project = projectMapper.selectById(payVo.getProjectId());
			// 校验是否已经无法缴费
			if (project.getEndTime().isBefore(LocalDateTime.now())) {
				throw new Exception("无法缴费");
			}
			String orderId = String.valueOf(System.nanoTime());
			payBase.setOfficeId(project.getOfficeId());
			payBase.setOrderId(orderId);
			// 订单金额的计算不能直接前端传，安全风险
			payBase.setOrderPrice(payVo.getActrualPrice().doubleValue());
			String callbackUrl = getPayNotifyUrl(project);
			payBase.setNotifyUrl(callbackUrl);
			payBase.setCallBackUrl(payVo.getCallBackUrl());
			// 构造商品类型
			PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(payVo.getSubjectIds().split(","));
			List<ProjectSubject> payProjectSubjects = payStudentSubjectDTO.getPayProjectSubjects();
			List<PayRequestGoodItem> goods = consGoods(payProjectSubjects);
			payBase.setGoods(goods);
			payBase.setDevice(BmPayDeviceEnum.PC.getDevice());
			try {
				log.info("paypc.payBase=[{}]", JSON.toJSON(payBase));
				map = (Map<String, Object>) tpsClient.pay(payBase);
				log.info("paypc.map=[{}]", JSON.toJSON(map));
				Boolean success = Boolean.valueOf(String.valueOf(map.get("success")));
				String msg = String.valueOf(map.get("msg"));
				if (!success) {
					map.put("msg", msg);
					return map;
				}
			} catch (Exception e) {
				log.info("tpsClient.pay 调用异常" , e);
				map.put("msg", "支付系统异常请稍后重试");
				return map;
			}
			String orderPayUrl = String.valueOf(map.get("obj"));
			// 保存订单信息
			Order payOrder = new Order();
			payOrder.setBmProjectId(payVo.getProjectId());
			payOrder.setId(orderId);
			payOrder.setOrderPaySupplier("PAY_ORDER");
			payOrder.setOrderPrice(payVo.getActrualPrice().doubleValue());
			payOrder.setOrderTime(DateUtils.getNowTime("yyyy-MM-dd HH:mm:ss"));
			payOrder.setOrderType("PAY_ORDER");
			// 未支付：考生发起支付，未付款 
			payOrder.setPayStatus(BmPayStatusEnum.UNPAY.getPayStatus().toString());
			payOrder.setRegId(payVo.getRegId());
			payOrder.setOrderPayUrl(orderPayUrl);
			payOrder.setCreateBy(iBaseLoginService.getUserId());
			payOrder.setCreateDate(LocalDateTime.now());
			payOrder.setUpdateBy(iBaseLoginService.getUserId());
			payOrder.setUpdateDate(LocalDateTime.now());
			payOrder.setOrderPayUrl(orderPayUrl);
			orderMapper.insertOrder(payOrder);

			// 保存订单内容表信息
			Map<String, Object> orderDetails = new HashMap<String, Object>();
			String orderDetailsId = UUIDUtils.newSortUUID();
			orderDetails.put("id", orderDetailsId);
			orderDetails.put("bm_order_id", orderId);
			// 报名费用
			orderDetails.put("business_type", BmCostType.COST_BM.getType());
			orderDetails.put("actrual_price", payVo.getActrualPrice());
			orderDetails.put("order_price", payVo.getPrice());
			orderDetails.put("coupon_price", payVo.getCouponPrice());
			orderDetails.put("is_coupon", "");
			orderDetails.put("pay_type", "L");
			orderDetails.put("coupon_activity_id", payVo.getCouponActivityId()); // 优惠活动的id
			orderDetails.put("create_date", LocalDateTime.now());
			orderDetails.put("update_date", LocalDateTime.now());
			orderDetails.put("is_group", "0");
			orderMapper.insertOrderDetails(orderDetails);

			// 保存订单报名科目明细表
			String[] subjectStrings = payVo.getSubjectIds().split(",");
			Map<String, ProjectSubject> studentProjectSubjectMap = payStudentSubjectDTO.getStudentProjectSubjectMap();
			String[] subjectPrices = payVo.getSubjectPriceList().split(",");
			for (int i = 0; i < subjectStrings.length; i++) {
				Map<String, Object> subject = new HashMap<String, Object>();
				subject.put("id", UUIDUtils.newSortUUID());
				subject.put("bm_student_subject_id", subjectStrings[i]);
				subject.put("reg_id", payVo.getRegId());//
				ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
				if (null != projectSubject && null != projectSubject.getPrice()) {
					subject.put("pay_subject_price", String.valueOf(projectSubject.getPrice()));
				} else {
					subject.put("pay_subject_price", subjectPrices[i]);
				}
				subject.put("bm_order_details_id", orderDetailsId);
				// 缴费中
				subject.put("bm_pay_status", BmMidOrderPayStatus.PAY_PEDDING.getPayStatus());
				subject.put("create_date", LocalDateTime.now());
				subject.put("update_date", LocalDateTime.now());
				subject.put("student_id", payVo.getStudentId());
				orderMapper.insertOrderSubject(subject);
			}
			// 记录支付流水
			for (int i = 0; i < subjectStrings.length; i++) {
				ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
				OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
				Long businessFlowId = UniqueIDUtils.generateId();
				orderBusinessFlow.setId(businessFlowId);
				orderBusinessFlow.setBmOrderId(payOrder.getId());
				orderBusinessFlow.setBmOrderDetailId(orderDetailsId);
				orderBusinessFlow.setBusinessType(BmCostType.COST_BM.getType());
				// 流水的状态为待支付
				orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
				if(null != projectSubject && null != projectSubject.getPrice()) {
					orderBusinessFlow.setOrderPrice(Double.valueOf(String.valueOf(projectSubject.getPrice())));
				}
				orderBusinessFlow.setOrderPaySupplier(payOrder.getOrderPaySupplier());
				orderBusinessFlow.setOrderType(payOrder.getOrderType());
				orderBusinessFlow.setBmProjectId(payOrder.getBmProjectId()); 
				orderBusinessFlow.setRegId(payVo.getRegId());
				orderBusinessFlow.setBmStudentSubjectId(subjectStrings[i]);
				orderBusinessFlow.setStudentId(payVo.getStudentId());
				orderBusinessFlow.setCreateDate(LocalDateTime.now());
				orderBusinessFlow.setUpdateDate(LocalDateTime.now());
				orderBusinessFlow.setDelFlag(Boolean.FALSE);
				orderBusinessFlowMapper.insert(orderBusinessFlow);
			}
		} catch (Exception e) {
			log.error("pc pay create order error", e);
			map.put("msg", e.toString());
			return map;
		}
		return map;
	}

	/***
	 * 获取支付配置的异步回调url
	 * @param project
	 * @return
	 */
	private String getPayNotifyUrl(Project project) {
		PayRequestVo payBase = getPayBase();
		String callbackUrl;
		String officeId = project.getOfficeId();
		StringBuilder callbackUrlSb = new StringBuilder();
		if (StringUtils.isEmpty(payBase.getNotifyUrlDoman())) {
			callbackUrlSb.append("http://");
			callbackUrlSb.append(payBase.getIp());
			callbackUrlSb.append(":");
			callbackUrlSb.append(payBase.getPort());
			String payProvider = PayProviderType.YIBAO.getType();
			try {
				log.info("## getPayNotifyUrl officeId:{}", officeId);
				payProvider = tpsClient.getPayProvider(officeId);
				log.info("## getPayNotifyUrl officeId:{}", payProvider);
			} catch (Exception e) {
				logger.error("## getPayProvider error", e);
			}
			if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/notifyUrl?officeId=");
			}
			if(PayProviderType.YIBAO.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/yopnotifyUrl?officeId=");
			}
			if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
                callbackUrlSb.append("/bm/studentPay/ncNonTaxPayNotifyUrl?officeId=");
            }
			callbackUrlSb.append(project.getOfficeId());
			callbackUrl = callbackUrlSb.toString();
		} else {
			callbackUrlSb.append(payBase.getNotifyUrlDoman());
			String payProvider = PayProviderType.YIBAO.getType();
			try {
				payProvider = tpsClient.getPayProvider(officeId);
			} catch (Exception e) {
				logger.error("## getPayProvider error", e);
			}
			if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/notifyUrl?officeId=");
			}
			if(PayProviderType.YIBAO.getType().equals(payProvider)) {
				callbackUrlSb.append("/bm/studentPay/yopnotifyUrl?officeId=");
			}
			if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
                callbackUrlSb.append("/bm/studentPay/ncNonTaxPayNotifyUrl?officeId=");
            }
			callbackUrlSb.append(project.getOfficeId());
			callbackUrl = callbackUrlSb.toString();
		}
		return callbackUrl;
	}

	/***
	 * 构建订单商品信息
	 * @param payProjectSubjects
	 * @return
	 */
	private List<PayRequestGoodItem> consGoods(List<ProjectSubject> payProjectSubjects) {
		List<PayRequestGoodItem> goods = new ArrayList<PayRequestGoodItem>();
		if(CollectionUtils.isEmpty(payProjectSubjects)) {
			return goods;
		}
		for (ProjectSubject projectSubject : payProjectSubjects) {
			PayRequestGoodItem payRequestGoodItem = new PayRequestGoodItem();
			payRequestGoodItem.setName(projectSubject.getSubjectName());
			payRequestGoodItem.setDescription(projectSubject.getSubjectName());
			payRequestGoodItem.setReceiver(projectSubject.getRemark());
			payRequestGoodItem.setAmount(Double.valueOf(String.valueOf(projectSubject.getPrice())));
			goods.add(payRequestGoodItem);
		}
		return goods;
	}

	/**
	 *获取缴费的报名项目
	 * @param
	 * @return
	 */
	private PayStudentSubjectDTO getPayProjectSubject(String[] subjectArry) {
		PayStudentSubjectDTO payStudentSubjectDTO = new PayStudentSubjectDTO();
		List<ProjectSubject> bmProjectSubjects = new ArrayList<>();
		List<StudentSubject> bmStudentSubjects = new ArrayList<>();
		Map<String, ProjectSubject> studentProjectSubjectMap = new HashMap<>();
		if(null == subjectArry || subjectArry.length ==0 ) {
			return null;
		}
		
		BigDecimal paytTotlePrice = BigDecimal.ZERO; 
		for (String studentSubjectId : subjectArry) {
			StudentSubject studentSubject = studentSubjectMapper.getStudentSubjectById(studentSubjectId);
			if(null != studentSubject) {
				ProjectSubject projectSubject = iProjectSubjectService.queryBySubjectId(studentSubject.getProjectId(), studentSubject.getSubjectId());
				if(null != projectSubject && BmProjectNeedPayEnum.PAY.getPayStatus().equals(projectSubject.getIsPay())) {
					bmStudentSubjects.add(studentSubject);
					bmProjectSubjects.add(projectSubject);
					studentProjectSubjectMap.put(studentSubjectId, projectSubject);
					paytTotlePrice=paytTotlePrice.add(projectSubject.getPrice());
				}
			}
		}
		payStudentSubjectDTO.setPayProjectSubjects(bmProjectSubjects);
		payStudentSubjectDTO.setStudentSubject(bmStudentSubjects);
		payStudentSubjectDTO.setStudentProjectSubjectMap(studentProjectSubjectMap);
		payStudentSubjectDTO.setPaytTotlePrice(paytTotlePrice);
		return payStudentSubjectDTO;
	}

	/**
	 * 去支付
	 */

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> payWeChat(PayVo payVo, HttpServletRequest request) {
		// 项目信息
		Map<String, Object> map = new HashMap<>();
		try {
			String[] subjectStrings = payVo.getSubjectIds().split(",");
			PayRequestVo payBase = getPayBase();
			
			Project project = projectMapper.selectById(payVo.getProjectId());
			// 校验缴费开始考试时间
			if(BmProjectNeedPayEnum.PAY.getPayStatus().equals(project.getIsPay())){
			    if(null != project.getPayBeginTime() && LocalDateTime.now().isBefore(project.getPayBeginTime())) {
			        Result result = new Result();
			        result.setResult("-1", "未到缴费开始时间");
			        return  BeanUtil.beanToMap(result);
			    }
			    if(null != project.getPayEndTime() && LocalDateTime.now().isAfter(project.getPayEndTime())) {
                    Result result = new Result();
                    result.setResult("-1", "报名项目已经超过缴费时间");
                    return  BeanUtil.beanToMap(result);
                }
			}
			// 订单号，唯一(订单号规则：8位数自增长从10000001开始)
			String orderId = String.valueOf(System.nanoTime());
			PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(payVo.getSubjectIds().split(","));
			String clientIp = getLocalIp(request);
			payBase.setOfficeId(project.getOfficeId());
			payBase.setOrderId(orderId);
			payBase.setOrderPrice(payVo.getActrualPrice().doubleValue());
			String callbackUrl = getPayNotifyUrl(project);
			payBase.setNotifyUrl(callbackUrl);
			payBase.setCallBackUrl(payVo.getCallBackUrl());
			payBase.setClientIp(clientIp);
			payBase.setDevice(BmPayDeviceEnum.APPLET.getDevice());
			String channel = payVo.getChannel();
            payBase.setOpenId(uaUserExtService.getopenidbyjscode(payVo.getJsCode(), "", "", channel));
			try {
				log.info("## payWeChat.payBase=[{}]", FastJsonUtil.getBeanToJson(payBase));
				map = (Map<String, Object>) tpsClient.payWechat(payBase);
				log.info("## payWeChat.map=[{}]", FastJsonUtil.getBeanToJson(map));
			} catch (Exception e) {
				log.info("## payWeChat call error" , e);
				// 把异常抛出去
				throw e;
			}
			// 保存订单信息
			Order entity = new Order();
			entity.setBmProjectId(payVo.getProjectId());
			entity.setId(orderId);
			entity.setOrderPaySupplier("PAY_ORDER");
			entity.setOrderPrice(payVo.getActrualPrice().doubleValue());
			entity.setOrderTime(DateUtils.getNowTime("yyyy-MM-dd HH:mm:ss"));
			entity.setOrderType("PAY_ORDER");
			entity.setPayStatus(BmPayStatusEnum.UNPAY.getPayStatus().toString());
			entity.setRegId(payVo.getRegId());
			entity.setCreateBy(iBaseLoginService.getUserId());
			entity.setCreateDate(LocalDateTime.now());
			entity.setUpdateBy(iBaseLoginService.getUserId());
			entity.setUpdateDate(LocalDateTime.now());
			entity.setStudentId(payVo.getStudentId());
			orderMapper.insertOrder(entity);
			log.info("## payWeChat.insertOrder=[{}]", FastJsonUtil.getBeanToJson(entity));
			// 保存订单内容表信息
			Map<String, Object> orderDetails = new HashMap<String, Object>();
			String orderDetailsId = UUIDUtils.newSortUUID();
			orderDetails.put("id", orderDetailsId);
			orderDetails.put("bm_order_id", orderId);
			orderDetails.put("business_type", BmCostType.COST_BM.getType());// 报名
			orderDetails.put("actrual_price", payVo.getActrualPrice());
			orderDetails.put("order_price", payVo.getPrice());
			orderDetails.put("coupon_price", payVo.getCouponPrice());
			orderDetails.put("is_coupon", "");
			orderDetails.put("pay_type", "L");
			orderDetails.put("coupon_activity_id", payVo.getCouponActivityId()); // 优惠活动的id
			orderDetails.put("create_date", LocalDateTime.now());
			orderDetails.put("update_date", LocalDateTime.now());
			orderDetails.put("is_group", "0");
			orderMapper.insertOrderDetails(orderDetails);

			// 保存订单报名科目明细表
			Map<String, ProjectSubject> studentProjectSubjectMap = payStudentSubjectDTO.getStudentProjectSubjectMap();
			String[] subjectPrices = payVo.getSubjectPriceList().split(",");
			for (int i = 0; i < subjectStrings.length; i++) {
				Map<String, Object> subject = new HashMap<String, Object>();
				subject.put("id", UUIDUtils.newSortUUID());
				subject.put("bm_student_subject_id", subjectStrings[i]);
				subject.put("reg_id", payVo.getRegId());//
				ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
				if (null != projectSubject && null != projectSubject.getPrice()) {
					subject.put("pay_subject_price", String.valueOf(projectSubject.getPrice()));
				} else {
					subject.put("pay_subject_price", subjectPrices[i]);
				}
				subject.put("bm_order_details_id", orderDetailsId);
				subject.put("bm_pay_status", BmMidOrderPayStatus.PAY_PEDDING.getPayStatus());
				subject.put("create_date", LocalDateTime.now());
				subject.put("update_date", LocalDateTime.now());
				subject.put("student_id", payVo.getStudentId());
				orderMapper.insertOrderSubject(subject);
			}
			
			// 记录支付流水
			for (int i = 0; i < subjectStrings.length; i++) {
				ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
				OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
				Long businessFlowId = UniqueIDUtils.generateId();
				orderBusinessFlow.setId(businessFlowId);
				orderBusinessFlow.setBmOrderId(entity.getId());
				orderBusinessFlow.setBmOrderDetailId(orderDetailsId);
				orderBusinessFlow.setBusinessType(BmCostType.COST_BM.getType());
				orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
				if(null != projectSubject && null != projectSubject.getPrice()) {
					orderBusinessFlow.setOrderPrice(Double.valueOf(String.valueOf(projectSubject.getPrice())));
				}
				orderBusinessFlow.setOrderPaySupplier(entity.getOrderPaySupplier());
				orderBusinessFlow.setOrderType(entity.getOrderType());
				orderBusinessFlow.setBmProjectId(entity.getBmProjectId()); 
				orderBusinessFlow.setRegId(payVo.getRegId());
				orderBusinessFlow.setBmStudentSubjectId(subjectStrings[i]);
				orderBusinessFlow.setStudentId(payVo.getStudentId());
				orderBusinessFlow.setCreateDate(LocalDateTime.now());
				orderBusinessFlow.setUpdateDate(LocalDateTime.now());
				orderBusinessFlow.setDelFlag(Boolean.FALSE);
				orderBusinessFlowMapper.insert(orderBusinessFlow);
			}
			
		} catch (Exception e) {
			log.error("## wechat pay create order error", e);
			map.put("msg", e.toString());
			return map;
		}
		return map;
	}

	public String getLocalIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值，第一个ip才是真实ip
			int index = ip.indexOf(",");
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		}
		ip = request.getHeader("X-Real-IP");
		if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			return ip;
		}
		return request.getRemoteAddr();

	}

	@Override
	public void updatePayStatus(JSONObject obj) {
		orderMapper.insertOrderReceiveNofity(obj);
	}

	private static final String ENCRYPT_KEY = "encryptKey";
	private static final String MERCHANT_ID = "merchantId";

	/**
	 * 解析回调订单数据
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> notifyUrl(HttpServletRequest req, String officeId) throws Exception {
		try {
			log.info("***********解析回调订单数据***************");
			log.info("pay notify officeId:{}", officeId);
			String encryptKey = req.getHeader(ENCRYPT_KEY);
			String merchantId = req.getHeader(MERCHANT_ID);
			JSONObject json = FastJsonUtils.convert(req.getInputStream());
			json.put(ENCRYPT_KEY, encryptKey);
			json.put(MERCHANT_ID, merchantId);
			log.info("pay notify encryptKey:[{}],merchantId:[{}] ", encryptKey, merchantId);
			log.info("pay notify jsondata:[{}] ", json.toString());
			Map<String, Object> map = new HashMap<String, Object>();
			Analysis analysis = new Analysis();
			analysis.setJsonObject(json.toString());
			analysis.setOfficeId(officeId);
			// 第三方解析回调数据
			map = (Map<String, Object>) tpsClient.analysis(analysis);
			log.info("pay notify analysis:[{}]" , JSON.toJSON(map));
			Map<String, Object> obj = new HashMap<String, Object>();
			String bmOrderId = (String) map.get("requestId"); // 订单号
			
			// 获取分布式锁
			String redisLockValue = redisTemplate.opsForValue().get(bmOrderId);
			if(StringUtils.isNotEmpty(redisLockValue)) {
				return null;
			}
			String serialNumber = String.valueOf(map.get("serialNumber"));
			obj.put("id", UUIDUtils.newSortUUID());
			obj.put("merchantId", map.get("merchantId"));
			obj.put("bmOrderId", bmOrderId);
			obj.put("serialNumber", serialNumber);
			obj.put("totalRefundCount", map.get("totalRefundCount"));
			obj.put("totalRefundAmount", map.get("totalRefundAmount"));
			obj.put("orderCurrency", map.get("orderCurrency"));
			obj.put("orderAmount", map.get("orderAmount"));
			obj.put("status", map.get("status"));
			obj.put("completeDate", map.get("completeDateTime"));
			obj.put("clearingOrg", map.get("clearingOrg"));
			obj.put("paymentModeAlias", map.get("paymentModeAlias"));
			obj.put("realBankSeri", map.get("realBankSeri"));
			obj.put("bindCardId", map.get("bindCardId"));
			obj.put("remark", map.get("remark"));
			obj.put("hmac", map.get("hmac"));

			obj.put("createDate", DateUtil.getStringDate());
			obj.put("updateDate", DateUtil.getStringDate());
			// 保存订单回调表数据
			orderMapper.insertOrderReceiveNofity(obj);

			if ("SUCCESS".equals(map.get("status"))) {
				// 更新订单状态
				Order entity = orderMapper.selectById(bmOrderId);
				entity.setId(bmOrderId);
				// 支付成功
				entity.setPayStatus(BmPayStatusEnum.PAY.getPayStatus().toString());
				entity.setUpdateDate(LocalDateTime.now());
				orderMapper.updateById(entity);

				// 查询缴费订单关联的科目信息
				List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
				// 如果没有科目信息不同步
				if(CollectionUtils.isEmpty(subjectList)) {
					return null;
				}
				// 查询订单关联的报名科目, 先把订单的科目缴费状态变更
				List<String> studentSubjectIds = new ArrayList<String>();
				for (StudentSubject studentSubject : subjectList) {
					studentSubjectIds.add(studentSubject.getId());
					studentSubject.setPay(BmPayStatusEnum.PAY.getPayStatus());// 缴费成功
					studentSubject.setUpdateDate(LocalDateTime.now());
					studentSubject.setBmTime(LocalDateTime.now());
					// 更新报名科目状态
					studentSubjectMapper.updateById(studentSubject);
				}
				iStudentProjectService.ansycSubjectPayStatus(subjectList);
				// 更新缴费完成  1：缴费中,2：缴费完成,3：缴费失败
				orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_SUCCESS.getPayStatus());
				// 更新退款状态未默认值
				orderMapper.updateSubjectMidOrderRefundStatus(bmOrderId, studentSubjectIds, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());

				// 获取支付订单详情id
				for (StudentSubject studentSubject : subjectList) {
					OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
					List<String> businessStatus = new ArrayList<String>();
					businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
					List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, entity.getBmProjectId(), businessStatus , null, studentSubject.getId(), null);
					if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
						orderBusinessFlow = orderBusinessFlows.get(0);
						orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
						orderBusinessFlow.setSerialNumber(serialNumber);
						orderBusinessFlow.setUpdateDate(LocalDateTime.now());
						orderBusinessFlowMapper.updateById(orderBusinessFlow);
					}
				}
				// 成功之后上锁
				redisTemplate.opsForValue().set(bmOrderId, "SUCCESS", 86400L, TimeUnit.SECONDS);
			} else {
				// 更新订单状态
				Order entity = new Order();
				entity.setId(bmOrderId);
				entity.setPayStatus(BmPayStatusEnum.PAY_FAIL.getPayStatus().toString());// 支付失败
				entity.setUpdateDate(LocalDateTime.now());
				orderMapper.updateById(entity);


				List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
				// 如果没有科目信息不同步
				if(CollectionUtils.isEmpty(subjectList)) {
					return null;
				}
				// 记录支付失败流水
				List<String> studentSubjectIds = new ArrayList<String>();
				if(CollectionUtils.isNotEmpty(subjectList)) {
					for (StudentSubject studentSubject : subjectList) {
						studentSubjectIds.add(studentSubject.getId());
					}
					// 更新科目的支付状态信息 1：缴费中,2：缴费完成,3：缴费失败
					orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_FAIL.getPayStatus());

					for (StudentSubject studentSubject : subjectList) {
						OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
						List<String> businessStatus = new ArrayList<String>();
						businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
						businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
						List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, entity.getBmProjectId(), businessStatus, null, studentSubject.getId(), null);
						if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
							orderBusinessFlow = orderBusinessFlows.get(0);
							orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
							orderBusinessFlow.setSerialNumber(serialNumber);
							orderBusinessFlow.setUpdateDate(LocalDateTime.now());
							orderBusinessFlowMapper.updateById(orderBusinessFlow);
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("notifyUrl error", e);
			throw e;
		}
		return null;
	}


	
	@Override
	public IPage<OrderInfoVo> orderList(PageParam<OrderInfoVo> pageParam, String payStatus, String regId) {
		IPage<OrderInfoVo> page = orderMapper.orderList(pageParam, payStatus, regId);
		List<OrderInfoVo> list = page.getRecords();
		for (OrderInfoVo orderInfoVo : list) {
			if (orderInfoVo.getRefundStatus() == 0 || orderInfoVo.getRefundStatus() == 1 || orderInfoVo.getRefundStatus() == 2 || orderInfoVo.getRefundStatus() == 4) {
				// 展示退款内容
				orderInfoVo.setRefundInfo(orderMapper.refundSubjectListDetailNameList(orderInfoVo.getOrderId()));
			}
			String bmProjectId = orderInfoVo.getProjectId();
			Project project = iProjectService.getById(bmProjectId);
			// 计算当前是否允许退款
			if (null != project) {
				// 首先看项目是否允许退款,如果不允许退款，直接不如许
				if (project.getIsRefund().equals(1)) {
					orderInfoVo.setAllowRefund(Boolean.FALSE);
				}
				// 如果允许退款，查看是否已经过了退款时间
				LocalDateTime refuseTime = project.getRefuseTime();
				if (null != refuseTime && refuseTime.isBefore(LocalDateTime.now())) {
					orderInfoVo.setAllowRefund(Boolean.FALSE);
				}
			}
			StudentProject studentProject = iStudentProjectService.getProjectStudent(orderInfoVo.getProjectId(), orderInfoVo.getRegId());
			if (null != studentProject) {
				orderInfoVo.setStudentId(studentProject.getId());
			}
		}
		page.setRecords(list);
		return page;
	}

	/**
	 * 团体缴费-查询列表
	 */
	@Override
	public Map<String, Object> queryPayInfoList(String studentIds) {
		Map<String, Object> mapResult = new HashMap<>();
		List<StudentPayInfo> listStudentPayInfos = new ArrayList<StudentPayInfo>();
		if (StringUtils.isEmpty(studentIds)) {
			mapResult.put("code", "15043");
			return mapResult;
		}
		String[] strings = studentIds.split(",");
		for (String studentId : strings) {

			StudentPayInfo studentPayInfo = new StudentPayInfo();

			// 不允许60秒内同一个学生同一个任务发起两次支付
			String orderTime = studentPayMapper.getOrderTimeByStudentId(studentId);
			if (StringUtils.isNotBlank(orderTime)) {
				Date createDate = DateUtil.stringToDate(orderTime);
				long interval = (new Date().getTime() - createDate.getTime()) / 1000; // 计算两个日期时间的秒数
				Long payInterval = Long.parseLong("60");
				if (interval < payInterval) {
					// 这里强制停止缴费
					mapResult.put("code", "15038");
					return mapResult;
				}
			}

			// 考生姓名、任务名称
			Map<String, String> map = studentPayMapper.getStudentName(studentId);
			String studentName = map.get("studentName");
			String projectName = map.get("projectName");
			String projectId = map.get("projectId");

			studentPayInfo.setProjectId(projectId);
			studentPayInfo.setStudentName(studentName);
			studentPayInfo.setProjectName(projectName);

			// 考生证件号码
			String studentCard = studentPayMapper.getStudentCard(studentId);
			studentPayInfo.setStudentCard(studentCard);

			Project project = projectMapper.selectById(projectId);
			// 判断项目是否需要审核
			if (project.getIsPay() == 0) {
				// 项目设置不需要缴费
				mapResult.put("code", "15046");
				return mapResult;
			}
			// 项目需要审核
			String isVerify = null;
			if (project.getIsVerify() == 1) {
				isVerify = "1";
			}

			// 查询报名科目信息
			List<StudentSubjectList> list = studentPayMapper.getStuSubject(projectId, studentId, isVerify);
			if (CollUtil.isEmpty(list)) {
				mapResult.put("code", "15042");
				return mapResult;
			}
			// 考试科目拼接
			String subjectNameString = "";
			// id集合
			String idString = "";
			// 价格集合
			String subjectPriceList = "";
			// 报名费用
			BigDecimal price = new BigDecimal("0.00");
			for (StudentSubjectList sList : list) {
				subjectNameString += sList.getSubjectName() + ",";
				idString += sList.getId() + ",";
				if (null != sList.getPrice()) {
					subjectPriceList += sList.getPrice() + ",";
					price = price.add(sList.getPrice());
				}
				studentPayInfo.setRegId(sList.getRegId());
				studentPayInfo.setStudentId(sList.getStudentId());
			}
			studentPayInfo.setSubjectPriceList(subjectPriceList);
			studentPayInfo.setSubjectIds(idString);
			studentPayInfo.setPrice(price);
			studentPayInfo.setActrualPrice(price);
			studentPayInfo.setSubjectNames(subjectNameString.substring(0, subjectNameString.length() - 1));

			// 优惠活动（暂时没加）
			listStudentPayInfos.add(studentPayInfo);
		}

		mapResult.put("code", "14001");
		mapResult.put("data", listStudentPayInfos);
		return mapResult;
	}

	/**
	 * 缴费支付-团体
	 */
	@SuppressWarnings("unchecked")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, Object> payList(PayListVo payListVo) {
		Map<String, Object> map = new HashMap<>();
		if (payListVo == null || CollUtil.isEmpty(payListVo.getStudentPayInfo())) {
			map.put("flag", false);
			return map;
		}
		PayRequestVo payBase = getPayBase();
        String projectId = payListVo.getProjectId();
        if(StrUtil.isEmptyIfStr(projectId)) {
            map.put("flag", false);
            return map;
        }
        // 项目信息
        Project project = projectMapper.selectById(projectId);
        if(null == project) {
            map.put("flag", false);
            return map;
        }
        // 订单号，唯一(订单号规则：8位数自增长从10000001开始)
        String orderId = String.valueOf(System.nanoTime());
        String officeId = project.getOfficeId();
        payBase.setOfficeId(officeId);
        payBase.setOrderId(orderId);
        payBase.setOrderPrice(payListVo.getActrualPrice().doubleValue());
        String callbackUrl = "";
        callbackUrl = getPayNotifyUrl(project);
        payBase.setNotifyUrl(callbackUrl);
        payBase.setCallBackUrl(payListVo.getCallBackUrl());
        String studentId = getOrderStudentIds(payListVo.getStudentPayInfo());
        if(StrUtil.isNotBlank(studentId)) {
           StudentProject studentProject = studentProjectMapper.selectById(studentId);
           if(null != studentProject) {
               payBase.setUserName(studentProject.getName());
               payBase.setPhone(studentProject.getPhone());
           }
        }
        // 构造商品类型
        List<ProjectSubject> payProjectSubjects = new ArrayList<>();
        PayStudentSubjectDTO payStudentSubject = getPayProjectSubject(payListVo.getStudentPayInfo().get(0).getSubjectIds().split(","));
        if(null != payStudentSubject) {
            payProjectSubjects = payStudentSubject.getPayProjectSubjects();
            payBase.setOrderPrice(payStudentSubject.getPaytTotlePrice().doubleValue());
        }
        List<PayRequestGoodItem> goods = consGoods(payProjectSubjects);
        payBase.setGoods(goods);
        try {
            log.info("payList.payBase=[{}]", JSON.toJSON(payBase));
            map = (Map<String, Object>) tpsClient.pay(payBase);
            log.info("payList.resultMap=[{}]", JSON.toJSON(map));
        } catch (Exception e) {
            log.info("payList call error :" , e);
            map.put("flag", false);
            return map;
        }
        String orderPayUrl = String.valueOf(map.get("obj"));
        // 保存订单信息
        Order entity = new Order();
        entity.setBmProjectId(payListVo.getProjectId());
        entity.setId(orderId);
        String orderType = getOrderType(officeId);
        entity.setOrderPaySupplier(orderType);
        entity.setOrderPrice(payBase.getOrderPrice());
        entity.setOrderTime(DateUtils.getNowTime("yyyy-MM-dd HH:mm:ss"));
        entity.setOrderType(orderType);
        entity.setRegId(payListVo.getRegId());
        entity.setPayStatus(BmPayStatusEnum.UNPAY.getPayStatus().toString());
        entity.setStudentId(studentId);
        entity.setCreateBy(iBaseLoginService.getUserId());
        entity.setCreateDate(LocalDateTime.now());
        entity.setUpdateBy(iBaseLoginService.getUserId());
        entity.setUpdateDate(LocalDateTime.now());
        entity.setOrderPayUrl(orderPayUrl);
        orderMapper.insertOrder(entity);

        // 保存订单内容表信息
        Map<String, Object> orderDetails = new HashMap<String, Object>();
        String orderDetailsId = UUIDUtils.newSortUUID();
        orderDetails.put("id", orderDetailsId);
        orderDetails.put("bm_order_id", orderId);
        orderDetails.put("business_type", BmCostType.COST_BM.getType());// 报名
        orderDetails.put("actrual_price", payListVo.getActrualPrice().doubleValue());
        orderDetails.put("order_price", payListVo.getPrice().doubleValue());
        orderDetails.put("coupon_price", "0");
        orderDetails.put("is_coupon", "");
        orderDetails.put("pay_type", "L");
        orderDetails.put("coupon_activity_id", ""); // 优惠活动的id
        orderDetails.put("create_date", LocalDateTime.now());
        orderDetails.put("update_date", LocalDateTime.now());
        orderDetails.put("is_group", "1");
        orderMapper.insertOrderDetails(orderDetails);

        // 保存订单报名科目明细表
        for (StudentPayInfo payVo : payListVo.getStudentPayInfo()) {
            String[] subjectStrings = payVo.getSubjectIds().split(",");
            PayStudentSubjectDTO payStudentSubjectDTO = getPayProjectSubject(payVo.getSubjectIds().split(","));
            Map<String, ProjectSubject> studentProjectSubjectMap = new HashMap<>();
            if(null != payStudentSubjectDTO ) {
                studentProjectSubjectMap = payStudentSubjectDTO.getStudentProjectSubjectMap();
            }
            String[] subjectPrices = payVo.getSubjectPriceList().split(",");
            for (int i = 0; i < subjectStrings.length; i++) {
                Map<String, Object> subject = new HashMap<>();
                subject.put("id", UUIDUtils.newSortUUID());
                subject.put("bm_student_subject_id", subjectStrings[i]);
                subject.put("reg_id", payVo.getRegId());//
                ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
                if (null != projectSubject && null != projectSubject.getPrice()) {
                    subject.put("pay_subject_price", String.valueOf(projectSubject.getPrice()));
                } else {
                    subject.put("pay_subject_price", subjectPrices[i]);
                }
                subject.put("bm_order_details_id", orderDetailsId);
                subject.put("create_date", LocalDateTime.now());
                subject.put("update_date", LocalDateTime.now());
                subject.put("student_id", payVo.getStudentId());
                orderMapper.insertOrderSubject(subject);
            }
            // 记录支付流水
            for (int i = 0; i < subjectStrings.length; i++) {
                ProjectSubject projectSubject = studentProjectSubjectMap.get(subjectStrings[i]);
                OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
                Long businessFlowId = UniqueIDUtils.generateId();
                orderBusinessFlow.setId(businessFlowId);
                orderBusinessFlow.setBmOrderId(entity.getId());
                orderBusinessFlow.setBmOrderDetailId(orderDetailsId);
                orderBusinessFlow.setBusinessType(BmCostType.COST_BM.getType());
                orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
                if(null != projectSubject && null != projectSubject.getPrice()) {
                    orderBusinessFlow.setOrderPrice(Double.valueOf(String.valueOf(projectSubject.getPrice())));
                }
                orderBusinessFlow.setOrderPaySupplier(entity.getOrderPaySupplier());
                orderBusinessFlow.setOrderType(entity.getOrderType());
                orderBusinessFlow.setBmProjectId(entity.getBmProjectId());
                orderBusinessFlow.setRegId(payVo.getRegId());
                orderBusinessFlow.setBmStudentSubjectId(subjectStrings[i]);
                orderBusinessFlow.setStudentId(payVo.getStudentId());
                orderBusinessFlow.setCreateDate(LocalDateTime.now());
                orderBusinessFlow.setUpdateDate(LocalDateTime.now());
                orderBusinessFlow.setDelFlag(Boolean.FALSE);
                orderBusinessFlowMapper.insert(orderBusinessFlow);
            }
        }
		map.put("flag", true);
		return map;
	}
	
    /**
     * 获取订单的考生id
     * 
     * @param studentPayInfo
     * @return
     */
    private String getOrderStudentIds(List<StudentPayInfo> studentPayInfos) {
        if (CollUtil.isEmpty(studentPayInfos)) {
            return StrUtil.EMPTY;
        }
        StringBuilder stringBuilder = new StringBuilder();
        if(studentPayInfos.size() > 2) {
            throw new RuntimeException("请单个考生支付，避免错误");
        }
        for (StudentPayInfo studentPayInfo : studentPayInfos) {
            stringBuilder.append(studentPayInfo.getStudentId());
            stringBuilder.append(",");
        }
        return  stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString();
    }

    private String getOrderType(String officeId) {
        String payProvider = PayProviderType.YIBAO.getType();
        try {
            log.info("## getOrderType officeId:{}", officeId);
            payProvider = tpsClient.getPayProvider(officeId);
            log.info("## getOrderType officeId:{}", payProvider);
        } catch (Exception e) {
            logger.error("## getOrderType error", e);
        }
        if(PayProviderType.SHOUYIXIN.getType().equals(payProvider)) {
            return "SHOU_YI_XIN";
        }
        if(PayProviderType.YIBAO.getType().equals(payProvider)) {
            return "YIBAO";
        }
        if(PayProviderType.NANCHANGFEISHUI.getType().equals(payProvider)) {
            return "NANCHANGFEISHUI";
        }
        return "WEIZHI";
    }
	
	

	@Override
	public Map<String, Object> notifyUrl(PeePayNotify peePayNotify, Map<String, String> queryMap) {
		try {
			log.info("## ybnotifyUrl params:[{}]" , FastJsonUtil.getBeanToJson(peePayNotify));
			String r5_Pid = queryMap.get("r5_Pid");
			if(StringUtils.isNotEmpty(r5_Pid)) {
				r5_Pid = URLDecoder.decode(r5_Pid, "GBK");
			}
			peePayNotify.setR5_Pid(r5_Pid);
			boolean flag = tpsClient.peePayHmac(peePayNotify);
			log.info("## ybnotifyUrl peePayHmac result:[{}]" , flag);
			if (!flag) {
				throw new Exception("数据签名验证失败，" + peePayNotify.getHmac_safe());
			}
			// 第三方解析回调数据
			// 订单号
			String bmOrderId = peePayNotify.getR6_Order();
			if(StringUtils.isEmpty(bmOrderId)) {
				log.info("## ybnotifyUrl回调参数订单号缺失:[{}]" , bmOrderId);
				throw new Exception("易宝支付回调参数订单号缺失");
			}
			// 首先判断订单号是不是存在
			Order payOrder = orderMapper.selectById(bmOrderId);
			if(null == payOrder || StringUtils.isEmpty(payOrder.getBmProjectId())) {
				log.info("## ybnotifyUrl回调参数订单号查询不到订单信息:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
				throw new Exception("易宝支付回调参数订单号查询不到订单信息");
			}
			Project payProject = projectMapper.selectById(payOrder.getBmProjectId());
			if(null == payProject) {
				log.info("## ybnotifyUrl回调参数订单号查询不到报名项目信息:[{}]" , FastJsonUtil.getBeanToJson(payProject));
				throw new Exception("易宝支付回调参数订单号查询不到报名项目信息");
			}
			// 获取分布式锁
			String redisLockValue = redisTemplate.opsForValue().get(bmOrderId);
			if(StringUtils.isNotEmpty(redisLockValue)) {
				return null;
			}
			
			Map<String, Object> obj = new HashMap<String, Object>();
			// 易宝交易流水号, 易宝支付平台产生的交易流水号，每笔订单唯一
			String serialNumber = String.valueOf(peePayNotify.getR2_TrxId());
			obj.put("id", UUIDUtils.newSortUUID());
			// 商户编号
			obj.put("merchantId", peePayNotify.getP1_MerId());
			// 支付订单号
			obj.put("bmOrderId", bmOrderId);
			// 易宝交易流水号, 易宝支付平台产生的交易流水号，每笔订单唯一
			obj.put("serialNumber", serialNumber);
			// 已退款次数, 易宝支付不提供，先设置-1
			obj.put("totalRefundCount", "-1");
			// 已退款金额, 易宝支付不提供，先设置-1
			obj.put("totalRefundAmount", "-1");
			// 订单币种 默认人民币 CNY
			obj.put("orderCurrency", "CNY");
			// 单位:分, 支付金额 单位：元, 这里是不是需要转换成分
			obj.put("orderAmount", peePayNotify.getR3_Amt());
			// 银行订单号
			obj.put("realBankSeri", peePayNotify.getRo_BankOrderId());
			// 固定值：1 - 代表支付成功
			obj.put("status", YbPayResultCodeEnum.SUCCESS.getCode().equals(peePayNotify.getR1_Code()) ? "SUCCESS" : "FAILED");
			// 商户的拓展信息
			obj.put("remark", peePayNotify.getR8_MP());
			// 支付成功时间
			if (StringUtils.isNotBlank(peePayNotify.getRp_PayDate())) {
				DateFormat format2 = new SimpleDateFormat("yyyyMMddHHmmss");
				obj.put("completeDate", format2.parse(peePayNotify.getRp_PayDate()));// 20210128114405
			}
			// 清算机构
			obj.put("clearingOrg", payProject.getOfficeId());
			// 支付方式
			obj.put("paymentModeAlias", "易宝支付");
			// 用户绑卡id
			obj.put("bindCardId", "-1");
			
			// 签名数据 Max(32) 产生 hmac 需要两个参数：参数 1: STR，列表中的参数值按照签名顺序拼接所产生的字符串，注意 null 要转换为””，并确保无乱码；参数2: 商户密钥。
			obj.put("hmac", peePayNotify.getHmac_safe() + "_" + peePayNotify.getHmac());
			obj.put("createDate", DateUtil.getStringDate());
			obj.put("updateDate", DateUtil.getStringDate());

			log.info("## ybnotifyUrl insertOrderReceiveNofity obj:[{}]" , FastJsonUtil.getBeanToJson(obj));
			// 保存订单回调表数据
			orderMapper.insertOrderReceiveNofity(obj);
			
			// 固定值：1 - 代表支付成功
			if (YbPayResultCodeEnum.SUCCESS.getCode().equals(peePayNotify.getR1_Code())) {
				payOrder.setId(bmOrderId);
				payOrder.setPayStatus(BmPayStatusEnum.PAY.getPayStatus().toString());// 支付成功
				payOrder.setUpdateDate(LocalDateTime.now());
				orderMapper.updateById(payOrder);
				log.info("## ybnotifyUrl order updateById entity:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
				// 查询订单关联的报名科目
				List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());

				log.info("## ybnotifyUrl query subjectList [{}]" , FastJsonUtil.getBeanToJson(subjectList));
				// 如果没有科目信息不同步
				if(CollectionUtils.isEmpty(subjectList)) {
					return null;
				}
				// 查询订单关联的报名科目, 先把订单的科目缴费状态变更
				List<String> studentSubjectIds = new ArrayList<String>();
				for (StudentSubject studentSubject : subjectList) {
					studentSubjectIds.add(studentSubject.getId());
					studentSubject.setPay(BmPayStatusEnum.PAY.getPayStatus());// 缴费成功
					studentSubject.setUpdateDate(LocalDateTime.now());
					studentSubject.setBmTime(LocalDateTime.now());
					// 更新报名科目状态
					studentSubjectMapper.updateById(studentSubject);
				}
				iStudentProjectService.ansycSubjectPayStatus(subjectList);
				
				// 更新缴费完成  1：缴费中,2：缴费完成,3：缴费失败
				orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_SUCCESS.getPayStatus());
				// 更新退款状态未默认值
				orderMapper.updateSubjectMidOrderRefundStatus(bmOrderId, studentSubjectIds, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
				// 更新支付流水状态
				for (StudentSubject studentSubject : subjectList) {
					OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
					List<String> businessStatus = new ArrayList<String>();
					businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
					businessStatus.add(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
					List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, payOrder.getBmProjectId(), businessStatus , null, studentSubject.getId(), null);
					if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
						orderBusinessFlow = orderBusinessFlows.get(0);
						orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
						orderBusinessFlow.setSerialNumber(serialNumber);
						orderBusinessFlow.setUpdateDate(LocalDateTime.now());
						orderBusinessFlowMapper.updateById(orderBusinessFlow);
					}
				}
				log.info("## ybnotifyUrl syncKw [{}]" , "ok");
				// 记录一条支付流水
			} else {
				// 更新订单状态
				Order entity = new Order();
				entity.setId(bmOrderId);
				entity.setPayStatus(BmPayStatusEnum.PAY_FAIL.getPayStatus().toString());// 支付失败
				entity.setUpdateDate(LocalDateTime.now());
				orderMapper.updateById(entity);
				List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
				// 如果没有科目信息不同步
				if(CollectionUtils.isEmpty(subjectList)) {
					return null;
				}
				// 记录支付失败流水
				List<String> studentSubjectIds = new ArrayList<String>();
				if(CollectionUtils.isNotEmpty(subjectList)) {
					for (StudentSubject studentSubject : subjectList) {
						studentSubjectIds.add(studentSubject.getId());
					}
					// 更新科目的支付状态信息 1：缴费中,2：缴费完成,3：缴费失败
					orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_FAIL.getPayStatus());

					for (StudentSubject studentSubject : subjectList) {
						OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
						List<String> businessStatus = new ArrayList<String>();
						businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
						businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
						List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, entity.getBmProjectId(), businessStatus, null, studentSubject.getId(), null);
						if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
							orderBusinessFlow = orderBusinessFlows.get(0);
							orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
							orderBusinessFlow.setSerialNumber(serialNumber);
							orderBusinessFlow.setUpdateDate(LocalDateTime.now());
							orderBusinessFlowMapper.updateById(orderBusinessFlow);
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("易宝支付支付信息异常", e);
		}
		return null;
	}

	@Override
	public Map<String, Object> poynotifyUrl(String customerIdentification, String orderJson) throws Exception {
	    if (StringUtils.isEmpty(orderJson) || StringUtils.isEmpty(customerIdentification)) {
            throw new Exception("数据签名验证失败");
        }
        OrderQueryYopQueryOrderResDTOResultTemp orderQueryYopQueryOrderResDTOResultTemp = JsonUtil.fromJson(orderJson, OrderQueryYopQueryOrderResDTOResultTemp.class);
        String payInfo = orderQueryYopQueryOrderResDTOResultTemp.getPayerInfo();
        OrderQueryPayerInfoResult payInfoTemp = JsonUtil.fromJson(payInfo, OrderQueryPayerInfoResult.class);
        
        OrderQueryYopQueryOrderResDTOResult orderQueryYopQueryOrderResDTOResult = new OrderQueryYopQueryOrderResDTOResult();
        BeanUtil.copyProperties(orderQueryYopQueryOrderResDTOResultTemp, orderQueryYopQueryOrderResDTOResult, "payerInfo");
        orderQueryYopQueryOrderResDTOResult.setPayerInfo(payInfoTemp);
        // 订单号
        String bmOrderId = orderQueryYopQueryOrderResDTOResult.getOrderId();
        if(StringUtils.isEmpty(bmOrderId)) {
            log.info("## ybnotifyUrl回调参数订单号缺失:[{}]" , bmOrderId);
            throw new Exception("易宝支付回调参数订单号缺失");
        }
        // 首先判断订单号是不是存在
        Order payOrder = orderMapper.selectById(bmOrderId);
        if(null == payOrder || StringUtils.isEmpty(payOrder.getBmProjectId())) {
            log.info("## ybnotifyUrl回调参数订单号查询不到订单信息:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
            throw new Exception("易宝支付回调参数订单号查询不到订单信息");
        }
        Project payProject = projectMapper.selectById(payOrder.getBmProjectId());
        if(null == payProject) {
            log.info("## ybnotifyUrl回调参数订单号查询不到报名项目信息:[{}]" , FastJsonUtil.getBeanToJson(payProject));
            throw new Exception("易宝支付回调参数订单号查询不到报名项目信息");
        }
        // 获取分布式锁
        String redisLockValue = redisTemplate.opsForValue().get(bmOrderId);
        if(StringUtils.isNotEmpty(redisLockValue)) {
            return MapUtil.empty();
        }
        
        Map<String, Object> obj = new HashMap<>();
        // 易宝交易流水号, 易宝支付平台产生的交易流水号，每笔订单唯一
        String serialNumber = orderQueryYopQueryOrderResDTOResult.getUniqueOrderNo();
        obj.put("id", UUIDUtils.newSortUUID());
        // 商户编号
        obj.put("merchantId", customerIdentification);
        // 支付订单号
        obj.put("bmOrderId", bmOrderId);
        // 易宝交易流水号, 易宝支付平台产生的交易流水号，每笔订单唯一
        obj.put("serialNumber", serialNumber);
        // 已退款次数, 易宝支付不提供，先设置-1
        obj.put("totalRefundCount", "-1");
        // 已退款金额, 易宝支付不提供，先设置-1
        obj.put("totalRefundAmount", "-1");
        // 订单币种 默认人民币 CNY
        obj.put("orderCurrency", "CNY");
        // 单位:分, 支付金额 单位：元, 这里是不是需要转换成分
        obj.put("orderAmount", orderQueryYopQueryOrderResDTOResult.getOrderAmount());
        // 银行订单号
        obj.put("realBankSeri", orderQueryYopQueryOrderResDTOResult.getBankOrderId());
        // 固定值：1 - 代表支付成功
        obj.put("status", orderQueryYopQueryOrderResDTOResult.getStatus());
        // 商户的拓展信息
        obj.put("remark", "");
        // 支付成功时间
        if (StringUtils.isNotBlank(orderQueryYopQueryOrderResDTOResult.getPaySuccessDate())) {
            DateFormat format2 = new SimpleDateFormat("yyyyMMddHHmmss");
            obj.put("completeDate", format2.parse(orderQueryYopQueryOrderResDTOResult.getPaySuccessDate()));// 20210128114405
        }
        // 清算机构
        obj.put("clearingOrg", payProject.getOfficeId());
        // 获取支付渠道
        String channel = orderQueryYopQueryOrderResDTOResult.getChannel();
        String paymentModeAlias = "易宝支付";
        if(StringUtils.isNotEmpty(channel) && "WECHAT".equals(channel)) {
            paymentModeAlias += "【微信支付】";
        }else if(StringUtils.isNotEmpty(channel) && "ALIPAY".equals(channel)) {
            paymentModeAlias += "【支付宝支付】";
        }else if(StringUtils.isNotEmpty(channel) && "NCPAY".equals(channel)) {
            paymentModeAlias += "【银联支付】";
        }
        // 支付方式
        obj.put("paymentModeAlias", paymentModeAlias);
        if(null != orderQueryYopQueryOrderResDTOResult.getPayerInfo()) {
            // 用户绑卡id
            obj.put("bindCardId", orderQueryYopQueryOrderResDTOResult.getPayerInfo().getBankCardNo());
        }
        
        
        // 签名数据 Max(32) 产生 hmac 需要两个参数：参数 1: STR，列表中的参数值按照签名顺序拼接所产生的字符串，注意 null 要转换为””，并确保无乱码；参数2: 商户密钥。
        obj.put("hmac", orderJson);
        obj.put("createDate", DateUtil.getStringDate());
        obj.put("updateDate", DateUtil.getStringDate());
        log.info("## ybnotifyUrl insertOrderReceiveNofity obj:[{}]" , FastJsonUtil.getBeanToJson(obj));
        // 保存订单回调表数据
        orderMapper.insertOrderReceiveNofity(obj);
        
        // 固定值：1 - 代表支付成功
        if ("SUCCESS".equals(orderQueryYopQueryOrderResDTOResult.getStatus())) {
            payOrder.setId(bmOrderId);
            payOrder.setPayStatus(BmPayStatusEnum.PAY.getPayStatus().toString());// 支付成功
            payOrder.setUpdateDate(LocalDateTime.now());
            orderMapper.updateById(payOrder);
            log.info("## ybnotifyUrl order updateById entity:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
            // 查询订单关联的报名科目
            List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
            log.info("## ybnotifyUrl query subjectList [{}]" , FastJsonUtil.getBeanToJson(subjectList));
            // 如果没有科目信息不同步
            if(CollectionUtils.isEmpty(subjectList)) {
                return MapUtil.empty();
            }
            // 查询订单关联的报名科目, 先把订单的科目缴费状态变更
            List<String> studentSubjectIds = new ArrayList<>();
            for (StudentSubject studentSubject : subjectList) {
                studentSubjectIds.add(studentSubject.getId());
                studentSubject.setPay(BmPayStatusEnum.PAY.getPayStatus());// 缴费成功
                studentSubject.setUpdateDate(LocalDateTime.now());
                studentSubject.setBmTime(LocalDateTime.now());
                // 更新报名科目状态
                studentSubjectMapper.updateById(studentSubject);
            }
            iStudentProjectService.ansycSubjectPayStatus(subjectList);
            // 更新缴费完成  1：缴费中,2：缴费完成,3：缴费失败
            orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_SUCCESS.getPayStatus());
            // 更新退款状态未默认值
            orderMapper.updateSubjectMidOrderRefundStatus(bmOrderId, studentSubjectIds, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
            // 更新支付流水状态
            for (StudentSubject studentSubject : subjectList) {
                OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
                List<String> businessStatus = new ArrayList<>();
                businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
                businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
                businessStatus.add(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
                businessStatus.add(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
                List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, payOrder.getBmProjectId(), businessStatus , null, studentSubject.getId(), null);
                if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
                    orderBusinessFlow = orderBusinessFlows.get(0);
                    orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
                    orderBusinessFlow.setSerialNumber(serialNumber);
                    orderBusinessFlow.setUpdateDate(LocalDateTime.now());
                    orderBusinessFlowMapper.updateById(orderBusinessFlow);
                }
            }
            // 成功之后上锁，主要原因是防止支付系统二次回调，把已经处理好的业务数据二次修改了
            redisTemplate.opsForValue().set(bmOrderId, "SUCCESS", 86400L, TimeUnit.SECONDS);
        } else {
            // 更新订单状态
            Order entity = new Order();
            entity.setId(bmOrderId);
            entity.setPayStatus(BmPayStatusEnum.PAY_FAIL.getPayStatus().toString());// 支付失败
            entity.setUpdateDate(LocalDateTime.now());
            orderMapper.updateById(entity);
            List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
            // 如果没有科目信息不同步
            if(CollectionUtils.isEmpty(subjectList)) {
                return null;
            }
            // 记录支付失败流水
            List<String> studentSubjectIds = new ArrayList<String>();
            if(CollectionUtils.isNotEmpty(subjectList)) {
                for (StudentSubject studentSubject : subjectList) {
                    studentSubjectIds.add(studentSubject.getId());
                }
                // 更新科目的支付状态信息 1：缴费中,2：缴费完成,3：缴费失败
                orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_FAIL.getPayStatus());

                for (StudentSubject studentSubject : subjectList) {
                    OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
                    List<String> businessStatus = new ArrayList<String>();
                    businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
                    businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
                    List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, entity.getBmProjectId(), businessStatus, null, studentSubject.getId(), null);
                    if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
                        orderBusinessFlow = orderBusinessFlows.get(0);
                        orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
                        orderBusinessFlow.setSerialNumber(serialNumber);
                        orderBusinessFlow.setUpdateDate(LocalDateTime.now());
                        orderBusinessFlowMapper.updateById(orderBusinessFlow);
                    }
                }
            }
        }
		return obj;
	}

    /**
     * 南昌非税系统支付回调
     * @throws Exception 
     * @see com.hyt.it.ogt.kq.service.bm.service.IStudentPayService#ncNonTaxPayNotify(java.lang.String, java.lang.String)
     **/
    @Override
    @Transactional
    public NcNonTaxPayCallBackData ncNonTaxPayNotify(String merapp, String bmOrderId, String officeId, NcNonTaxPayCallBackParams ncNonTaxPayCallBackParams) throws Exception {
        if(StringUtils.isEmpty(officeId)) {
            log.info("## ncNonTaxPayNotify回调参数订单号缺失:[{}]" , bmOrderId);
            throw new Exception("南昌非税系统支付回调参数订单号缺失");
        }
        if(StringUtils.isEmpty(bmOrderId)) {
            log.info("## ncNonTaxPayNotify回调参数机构码缺失:[{}]" , officeId);
            throw new Exception("南昌非税系统支付回调参数订单号缺失");
        }
        // 首先判断订单号是不是存在
        Order payOrder = orderMapper.selectById(bmOrderId);
        if(null == payOrder || StringUtils.isEmpty(payOrder.getBmProjectId())) {
            log.info("## ncNonTaxPayNotify回调参数订单号查询不到订单信息:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
            throw new Exception("易宝支付回调参数订单号查询不到订单信息");
        }
        Project payProject = projectMapper.selectById(payOrder.getBmProjectId());
        if(null == payProject) {
            log.info("## ncNonTaxPayNotify回调参数订单号查询不到报名项目信息:[{}]" , FastJsonUtil.getBeanToJson(payProject));
            throw new Exception("易宝支付回调参数订单号查询不到报名项目信息");
        }
        // 获取分布式锁
        String redisLockValue = redisTemplate.opsForValue().get(bmOrderId);
        log.info("## ncNonTaxPayNotify bmOrderId:[{}], redisLockValue [{}]" , bmOrderId, redisLockValue);
        if(StringUtils.isNotEmpty(redisLockValue)) {
            return new NcNonTaxPayCallBackData(bmOrderId, NcNonTaxPayCallBackData.oprStatus_success);
        }
        
        Map<String, Object> obj = new HashMap<>();
        // 易宝交易流水号, 易宝支付平台产生的交易流水号，每笔订单唯一
        obj.put("id", UUIDUtils.newSortUUID());
        // 支付订单号
        obj.put("bmOrderId", bmOrderId);
        // 固定值：1 - 代表支付成功
        obj.put("status", NcNonTaxPayCallBackData.oprStatus_success);
        // 商户的拓展信息
        obj.put("remark", "非税系统支付回调");
        // 支付方式
        obj.put("paymentModeAlias", PayProviderType.NANCHANGFEISHUI.name());
        // 平台流水号
        obj.put("serialNumber", ncNonTaxPayCallBackParams.getPlatformNo());
        // 订单金额
        obj.put("orderAmount", ncNonTaxPayCallBackParams.getAmount());
        // 商户id
        obj.put("merchantId", merapp);
       
        obj.put("createDate", DateUtil.getStringDate());
        obj.put("updateDate", DateUtil.getStringDate());
        log.info("## ncNonTaxPayNotify insertOrderReceiveNofity obj:[{}]" , FastJsonUtil.getBeanToJson(obj));
        // 保存订单回调表数据
        orderMapper.insertOrderReceiveNofity(obj);
        
        // 固定值：1 - 代表支付成功
        payOrder.setId(bmOrderId);
        payOrder.setPayStatus(BmPayStatusEnum.PAY.getPayStatus().toString());// 支付成功
        payOrder.setUpdateDate(LocalDateTime.now());
        orderMapper.updateById(payOrder);
        log.info("## ncNonTaxPayNotify order updateById entity:[{}]" , FastJsonUtil.getBeanToJson(payOrder));
        // 查询订单关联的报名科目
        List<StudentSubject> subjectList = studentSubjectMapper.getStuSubjectsByOrderIdAndOrderRefundStatus(bmOrderId, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
        log.info("## ncNonTaxPayNotify query subjectList [{}]" , FastJsonUtil.getBeanToJson(subjectList));
        // 如果没有科目信息不同步
        if(CollectionUtils.isEmpty(subjectList)) {
            return new NcNonTaxPayCallBackData(bmOrderId, NcNonTaxPayCallBackData.oprStatus_fail);
        }
        // 查询订单关联的报名科目, 先把订单的科目缴费状态变更
        List<String> studentSubjectIds = new ArrayList<>();
        for (StudentSubject studentSubject : subjectList) {
            studentSubjectIds.add(studentSubject.getId());
            studentSubject.setPay(BmPayStatusEnum.PAY.getPayStatus());// 缴费成功
            studentSubject.setUpdateDate(LocalDateTime.now());
            studentSubject.setBmTime(LocalDateTime.now());
            // 更新报名科目状态
            studentSubjectMapper.updateById(studentSubject);
        }
        iStudentProjectService.ansycSubjectPayStatus(subjectList);
        // 更新缴费完成  1：缴费中,2：缴费完成,3：缴费失败
        orderMapper.updateSubjectMidOrderPayStatus(bmOrderId, studentSubjectIds, BmMidOrderPayStatus.PAY_SUCCESS.getPayStatus());
        // 更新退款状态未默认值
        orderMapper.updateSubjectMidOrderRefundStatus(bmOrderId, studentSubjectIds, BmMidOrderPayRefundStatus.REFUND_DEFAULT.getRefundStatus());
        // 更新支付流水状态
        for (StudentSubject studentSubject : subjectList) {
            OrderBusinessFlow orderBusinessFlow = new OrderBusinessFlow();
            List<String> businessStatus = new ArrayList<>();
            businessStatus.add(BmPayBusinessFlowType.PAY_WAITTING.getBusinessType());
            businessStatus.add(BmPayBusinessFlowType.PAY_PEDDING.getBusinessType());
            businessStatus.add(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
            businessStatus.add(BmPayBusinessFlowType.PAY_FAIL.getBusinessType());
            List<OrderBusinessFlow> orderBusinessFlows = orderBusinessFlowMapper.getBusinessFlowByProjectIdAndRegId(bmOrderId, payOrder.getBmProjectId(), businessStatus , null, studentSubject.getId(), null);
            if(CollectionUtils.isNotEmpty(orderBusinessFlows)) {
                orderBusinessFlow = orderBusinessFlows.get(0);
                orderBusinessFlow.setBusinessStatus(BmPayBusinessFlowType.PAY_SUCCESS.getBusinessType());
                orderBusinessFlow.setSerialNumber("");
                orderBusinessFlow.setUpdateDate(LocalDateTime.now());
                orderBusinessFlowMapper.updateById(orderBusinessFlow);
            }
        }
        // 成功之后上锁，主要原因是防止支付系统二次回调，把已经处理好的业务数据二次修改了
        redisTemplate.opsForValue().set(bmOrderId, "SUCCESS", 86400L, TimeUnit.SECONDS);
        return new NcNonTaxPayCallBackData(bmOrderId, NcNonTaxPayCallBackData.oprStatus_success);
    }
}
